package com.vcredit.creditcat.util;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.net.util.Base64;

import com.vcredit.creditcat.exception.MobileValidateException;

/**
 * 工具包
 * 
 * @author kezhan
 *
 */
public class Utility {
	private static final char[] HEX_DIGITS = { 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102 };

	/**
	 * 分转元
	 */
	public static double spunYuan(Long spun) {
		return (double) spun / 100;
	}

	/**
	 * 元转分
	 */
	public static int yuanRPM(BigDecimal rpm) {
		return rpm.multiply(new BigDecimal(100)).intValue();
	}

	/**
	 * 非数字验证
	 * 
	 * @param num
	 * @return
	 */
	public static boolean digitalAuthentication(String num) {
		String str = "^\\d+$";
		return Pattern.compile(str).matcher(num).find();
	}

	/**
	 * 清除所有的多余空白
	 * 
	 * @param str
	 * @return
	 */
	public static String clearBlank(String word) {
		String regex = "[' ']+";
		Pattern p = Pattern.compile(regex);
		Matcher m = p.matcher(word);
		return m.replaceAll("");
	}

	/**
	 * 清除所有的指定特殊字符
	 * 
	 * @param word
	 * @param symbos
	 * @return
	 */
	public static String clearSpecialSymbo(String word, String[] symbos) {
		if (null == symbos || symbos.length == 0)
			return word;
		String regex = "[" + StringUtils.join(symbos, "|") + "]+";
		Pattern p = Pattern.compile(regex);
		Matcher m = p.matcher(word);
		return m.replaceAll("");
	}

	/**
	 * 格式化手机号码 过滤特殊字符：[ * ][ # ][ - ][ + ][ , ][ ; ]
	 * 
	 * @param phoneNo
	 * @param isMobile
	 * @return
	 * @throws MobileValidateException
	 */
	public static String formatPhoneNo(String phoneNo, boolean isMobile) throws MobileValidateException {
		if (null == phoneNo || StringUtils.isBlank(phoneNo)) {
			throw new MobileValidateException("号码为空");
		}
		phoneNo = clearBlank(phoneNo);
		phoneNo = clearSpecialSymbo(phoneNo, new String[] { "*", "#", "\\-", "+", ",", ";" });

		int len = phoneNo.length();
		if (len > 11) {
			phoneNo = phoneNo.substring(len - 11, len);
		} else if (len < 7) {
			throw new MobileValidateException("该号码长度不符合要求：" + phoneNo);
		}
		if (isMobile) {
			Pattern p = Pattern.compile("^1[3-9][0-9]{9}$");
			Matcher m = p.matcher(phoneNo);
			if (!m.matches()) {
				throw new MobileValidateException("该号码不是合法手机号码：" + phoneNo);
			}
		}
		return phoneNo;
	}

	/**
	 * 是否是手机号码
	 * 
	 * @param mobile
	 * @return
	 */
	public static boolean isMobileNo(String mobile) {
		Pattern p = Pattern.compile("^1[0-9]{10}$");
		Matcher m = p.matcher(mobile);
		return m.matches();
	}

	public static String unitMaxMin(Integer minNum, Integer maxNum) {
		StringBuilder sb = new StringBuilder();
		BigDecimal min = new BigDecimal(minNum).divide(new BigDecimal(10000).multiply(new BigDecimal(100)));
		BigDecimal max = new BigDecimal(maxNum).divide(new BigDecimal(10000).multiply(new BigDecimal(100)));
		return sb.append(min).append("-").append(max).append("万元").toString();
	}

	public static String unitMaxMinYUAN(Integer minNum, Integer maxNum) {
		StringBuilder sb = new StringBuilder();
		return sb.append(minNum / 100).append("-").append(maxNum / 100).append("元").toString();
	}

	/**
	 * 判断list是否为空
	 * 
	 * @param list
	 * @return
	 */
	public static Boolean isNullOrEmpty(Collection<?> list) {
		return null == list || list.isEmpty();
	}

	public static String clearWhiteSpace(String source) {
		StringBuffer sbf = new StringBuffer();
		Pattern p = Pattern.compile("\\s|\\n|\\t");
		Matcher m = p.matcher(source);
		while (m.find()) {
			System.out.println(m.group());
			m.appendReplacement(sbf, "");
		}
		m.appendTail(sbf);
		return source;
	}

	// Map --> Bean 2: 利用org.apache.commons.beanutils 工具类实现 Map --> Bean @autho
	// 张新功
	public static void transMap2Bean2(Map<String, Object> map, Object obj) {
		if (map == null || obj == null) {
			return;
		}
		try {
			BeanUtils.populate(obj, map);
		} catch (Exception e) {
			System.out.println("transMap2Bean2 Error " + e);
		}
	}

	// Map --> Bean 1: 利用Introspector,PropertyDescriptor实现 Map --> Bean @autho
	// 张新功
	public static void transMap2Bean(Map<String, Object> map, Object obj) {

		try {
			BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
			PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();

			for (PropertyDescriptor property : propertyDescriptors) {
				String key = property.getName();

				if (map.containsKey(key)) {
					Object value = map.get(key);
					// 得到property对应的setter方法
					Method setter = property.getWriteMethod();
					setter.invoke(obj, value);
				}

			}

		} catch (Exception e) {
			System.out.println("transMap2Bean Error " + e);
		}
		return;
	}

	// Bean --> Map 1: 利用Introspector和PropertyDescriptor 将Bean --> Map @autho
	// 张新功
	public static Map<String, Object> transBean2Map(Object obj) {

		if (obj == null) {
			return null;
		}
		Map<String, Object> map = new HashMap<String, Object>();
		try {
			BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
			PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
			for (PropertyDescriptor property : propertyDescriptors) {
				String key = property.getName();

				// 过滤class属性
				if (!key.equals("class")) {
					// 得到property对应的getter方法
					Method getter = property.getReadMethod();
					Object value = getter.invoke(obj);

					map.put(key, value);
				}

			}
		} catch (Exception e) {
			System.out.println("transBean2Map Error " + e);
		}

		return map;

	}

	/***
	 * 模糊匹配字符串
	 * 
	 * @param msg
	 * @param patt
	 * @return
	 */
	public static boolean regexMather(String msg, String patt) {
		Pattern pattern = Pattern.compile(patt);
		Matcher matcher = pattern.matcher(msg);
		return matcher.find();
	}

	/**
	 * 将String数组转为Long数组
	 * 
	 * @param strArr
	 * @return
	 */
	public static Long[] strArrToLongArr(String[] strArr) {
		Long[] longArr = new Long[strArr.length];
		for (int i = 0; i < strArr.length; i++) {
			longArr[i] = Long.parseLong(strArr[i]);
		}
		return longArr;
	}

	/**
	 * 将数组转为以,分隔的字符串
	 * 
	 * @param arr
	 * @return
	 */
	public static String arrToStr(Object[] arr) {
		if (null == arr) {
			return "";
		}
		StringBuilder sb = new StringBuilder();
		for (Object object : arr) {
			sb.append(object).append(",");
		}
		sb.delete(sb.length() - 1, sb.length());
		return sb.toString();
	}

	/**
	 * 生成一个不重复的编号
	 * 
	 * @param codeMark
	 * @return
	 */
	public static synchronized String nextCode(String codeMark) {
		String str = String.valueOf(System.currentTimeMillis());
		int random = (int) (Math.random() * (9999 - 1000 + 1) + 1000);
		str = str.substring(0, 6) + random + str.substring(6, str.length());
		return codeMark + str;
	}

	/**
	 * 日期字符串 转时间字符串
	 * 
	 * @param dateString
	 * @return
	 */
	public static String getDateTimeString(String dateString) {
		StringBuilder sb = new StringBuilder();
		if (StringUtils.isEmpty(dateString)) {
			return dateString;
		}

		sb.append(dateString);
		sb.append(" 00:00:00");

		return sb.toString();
	}

	/**
	 * @author yz
	 * @title 校验空
	 * @version v1.0
	 * @date 2017年7月26日 上午9:38:11
	 * @param obj
	 * @return
	 * @remark
	 */
	public static boolean checkEmpty(Object obj) {
		if (null == obj) {// 直接空
			return true;
		} else {// 非空
			if (obj instanceof Integer) {
				int it = ((Integer) obj).intValue();
				if (("" + it).length() > 0) {
					return false;
				}
			} else if (obj instanceof String) {
				String s = (String) obj;
				if (("" + s).length() > 0) {
					return false;
				}
			} else if (obj instanceof Double) {
				double d = ((Double) obj).doubleValue();
				if (("" + d).length() > 0) {
					return false;
				}
			} else if (obj instanceof Float) {
				float f = ((Float) obj).floatValue();
				if (("" + f).length() > 0) {
					return false;
				}
			} else if (obj instanceof Long) {
				long l = ((Long) obj).longValue();
				if (("" + l).length() > 0) {
					return false;
				}
			} else if (obj instanceof Boolean) {
				boolean b = ((Boolean) obj).booleanValue();
				if (("" + b).length() > 0) {
					return false;
				}
			} else if (obj instanceof Map) {
				Map m = (Map) obj;
				if (!m.isEmpty()) {
					return false;
				}
			} else if (obj instanceof HashMap) {
				HashMap m = (HashMap) obj;
				if (!m.isEmpty()) {
					return false;
				}
			} else if (obj instanceof List) {
				List l = (List) obj;
				if (l.size() > 0) {
					return false;
				}
			} else if (obj instanceof ArrayList) {
				ArrayList al = (ArrayList) obj;
				if (al.size() > 0) {
					return false;
				}
			}
			return true;// 默认空
		}
	}

	/**
	 * @author yz
	 * @title 校验非空
	 * @version v1.0
	 * @date 2017年7月26日 上午9:38:23
	 * @param obj
	 * @return
	 * @remark
	 */
	public static boolean checkNotEmpty(Object obj) {
		return !checkEmpty(obj);
	}

	/**
	 * 防止注入 验证 by chengxin
	 * 
	 * @param keyword
	 * @return
	 */
	public static boolean booleanescapeExprSpecialWord(String keyword) {
		if (StringUtils.isNotBlank(keyword)) {
			/*
			 * String[] fbsArr = { "\\", "$", "(", ")", "*", "+", ".", "[", "]
			 * ", "?", "^", "{", "}", "|", "'", "update", "insert", "delete",
			 * "1=1" };
			 */
			String[] fbsArr = { "\\", "$", "(", ")", "*", "+", "[", "]", "?", "^", "|", "update", "insert", "delete",
					"1=1" };
			for (String key : fbsArr) {
				if (keyword.contains(key)) {
					return false;
				}
			}
		} else {
			return false;
		}
		return true;
	}

	public static String getRandom(int length) {
		String sRs = "";
		Random random = new Random();
		String[] keys = new String[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f",
				"g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" };
		for (int i = 0; i < length; i++) {
			sRs = sRs + keys[random.nextInt(36)];
		}
		return sRs;
	}

	/**
	 * 根据身份证号 输出年龄
	 * 
	 * @param IdNO
	 * @return
	 */
	public static int IdNOToAge(String IdNO) {
		int leh = IdNO.length();
		String dates = "";
		if (leh == 18) {
			int se = Integer.valueOf(IdNO.substring(leh - 1)) % 2;
			dates = IdNO.substring(6, 10);
			SimpleDateFormat df = new SimpleDateFormat("yyyy");
			String year = df.format(new Date());
			int u = Integer.parseInt(year) - Integer.parseInt(dates);
			return u;
		} else {
			dates = IdNO.substring(6, 8);
			return Integer.parseInt(dates);
		}

	}

	/**
	 * 计算年龄 2017-10-19
	 * 
	 * @param dateOfBirth
	 * @return
	 */
	public static int getAge(Date dateOfBirth) {

		int age = 0;
		Calendar born = Calendar.getInstance();
		Calendar now = Calendar.getInstance();
		if (dateOfBirth != null) {
			now.setTime(new Date());
			born.setTime(dateOfBirth);
			if (born.after(now)) {
				throw new IllegalArgumentException("年龄不能超过当前日期");
			}
			age = now.get(Calendar.YEAR) - born.get(Calendar.YEAR);
			int nowDayOfYear = now.get(Calendar.DAY_OF_YEAR);
			int bornDayOfYear = born.get(Calendar.DAY_OF_YEAR);
			if (nowDayOfYear < bornDayOfYear) {
				age -= 1;
			}
		}
		return age;
	}

	/**
	 * 根据日期转成date类型
	 * 
	 * @param dates
	 * @param formate
	 * @return
	 * @throws ParseException
	 */
	public static Date getDates(String dates, String formate) throws ParseException {
		SimpleDateFormat sdf = new SimpleDateFormat(formate);// 小写的mm表示的是分钟
		Date date = sdf.parse(dates);
		return date;
	}

	/**
	 * 32位MD5加密
	 * 
	 * @param paramString
	 * @return
	 */
	public static String md5(String paramString) {
		try {
			MessageDigest localMessageDigest = MessageDigest.getInstance("MD5");
			localMessageDigest.update(paramString.getBytes());
			return toHexString(localMessageDigest.digest());
		} catch (NoSuchAlgorithmException localNoSuchAlgorithmException) {
			localNoSuchAlgorithmException.printStackTrace();
		}
		return paramString;
	}

	private static String toHexString(byte[] paramArrayOfByte) {
		int length = paramArrayOfByte.length;
		StringBuilder localStringBuilder = new StringBuilder(2 * length);
		for (int i = 0;; ++i) {
			if (i >= length)
				return localStringBuilder.toString().toUpperCase();
			localStringBuilder.append(HEX_DIGITS[((0xF0 & paramArrayOfByte[i]) >>> 4)]);
			localStringBuilder.append(HEX_DIGITS[(0xF & paramArrayOfByte[i])]);
		}
	}

	public static String addSystemTimesByDay(int days, String formatType) {
		Date date = new Date();
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.DAY_OF_MONTH, +days);// 今天的时间加days天
		date = calendar.getTime();
		SimpleDateFormat df = new SimpleDateFormat(formatType);
		return df.format(date);
	}

	public static int compareDate(String DATE1, String DATE2) {
		DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		try {
			Date dt1 = df.parse(DATE1);
			Date dt2 = df.parse(DATE2);
			if (dt1.getTime() > dt2.getTime()) {
				// System.out.println("时间戳:dt1>dt2");
				return 1;
			} else if (dt1.getTime() < dt2.getTime()) {
				// System.out.println("时间戳:dt1小于dt2");
				return -1;
			} else {
				return 0;
			}
		} catch (Exception exception) {
			exception.printStackTrace();
		}
		return 0;
	}

	public static int getAgeFromBirthTime(String birthTimeString) {
		// 先截取到字符串中的年、月、日
		String strs[] = birthTimeString.trim().split("-");
		int selectYear = Integer.parseInt(strs[0]);
		int selectMonth = Integer.parseInt(strs[1]);
		int selectDay = Integer.parseInt(strs[2]);
		// 得到当前时间的年、月、日
		Calendar cal = Calendar.getInstance();
		int yearNow = cal.get(Calendar.YEAR);
		int monthNow = cal.get(Calendar.MONTH) + 1;
		int dayNow = cal.get(Calendar.DATE);

		// 用当前年月日减去生日年月日
		int yearMinus = yearNow - selectYear;
		int monthMinus = monthNow - selectMonth;
		int dayMinus = dayNow - selectDay;

		int age = yearMinus;// 先大致赋值
		if (yearMinus < 0) {// 选了未来的年份
			age = 0;
		} else if (yearMinus == 0) {// 同年的，要么为1，要么为0
			if (monthMinus < 0) {// 选了未来的月份
				age = 0;
			} else if (monthMinus == 0) {// 同月份的
				if (dayMinus < 0) {// 选了未来的日期
					age = 0;
				} else if (dayMinus >= 0) {
					age = 1;
				}
			} else if (monthMinus > 0) {
				age = 1;
			}
		} else if (yearMinus > 0) {
			if (monthMinus < 0) {// 当前月>生日月
			} else if (monthMinus == 0) {// 同月份的，再根据日期计算年龄
				if (dayMinus < 0) {
				} else if (dayMinus >= 0) {
					age = age + 1;
				}
			} else if (monthMinus > 0) {
				age = age + 1;
			}
		}
		return age;
	}

	/**
	 * 四舍五入
	 * 
	 * @param decimalParam
	 * @return
	 */
	public static BigDecimal rounding(String decimalParam) {
		BigDecimal decimal = new BigDecimal(decimalParam);
		BigDecimal setScale = decimal.setScale(2, BigDecimal.ROUND_HALF_DOWN);
		return setScale;
	}

	/**
	 * 除法
	 * 
	 * @param b1
	 * @param b2
	 * @param scale
	 * @return
	 */
	public static double div(BigDecimal b1, BigDecimal b2, int scale) {
		if (scale < 0) {
			throw new IllegalArgumentException("The scale must be a positive integer or zero");
		}
		int r = b2.compareTo(BigDecimal.ZERO); // 和0，Zero比较
		if (r == 0) {
			return 0;
		} else {
			return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
		}
	}

	/**
	 * 除法
	 * 
	 * @param b1
	 * @param b2
	 * @param scale
	 * @return
	 */
	public static double divDouble(double a, double b, int scale) {
		if (scale < 0) {
			throw new IllegalArgumentException("The scale must be a positive integer or zero");
		}
		BigDecimal b1 = new BigDecimal(Double.toString(a));
		BigDecimal b2 = new BigDecimal(Double.toString(b));
		int r = b2.compareTo(BigDecimal.ZERO); // 和0，Zero比较
		if (r == 0) {
			return 0;
		} else {
			return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
		}
	}

	/**
	 * 提供精确的减法运算。
	 * 
	 * @param v1
	 *            被减数
	 * @param v2
	 *            减数
	 * @return 两个参数的差
	 */
	public static double sub(BigDecimal b1, double v2) {
		/*
		 * BigDecimal b1 = new BigDecimal(Double.toString(v1));
		 */
		BigDecimal b2 = new BigDecimal(Double.toString(v2));

		return b1.subtract(b2).doubleValue();
	}

	public static String imgBase64Str(String imgFilePath) throws Exception {// 将图片文件转化为字节数组字符串，并对其进行Base64编码处理

		byte[] data = null;
		try {
			// 创建URL
			URL url = new URL(imgFilePath);
			// 创建链接
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setRequestMethod("GET");
			conn.setConnectTimeout(30 * 1000);
			InputStream inStream = conn.getInputStream();

			ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
			byte[] buff = new byte[100];
			int rc = 0;
			while ((rc = inStream.read(buff, 0, 100)) > 0) {
				swapStream.write(buff, 0, rc);
			}
			data = swapStream.toByteArray();

			inStream.read(data);
			inStream.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		// 返回Base64编码过的字节数组字符串
		String result=Base64.encodeBase64String(data);
		return result.replace("\r\n", "");
	}

	/**
	 * 字符串的压缩
	 *
	 * @param bytes
	 *            待压缩的字符串
	 * @return 返回压缩后的字符串
	 * @throws IOException
	 */
	public static byte[] compress(byte[] bytes) {
		if (bytes == null) {
			return null;
		}
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		GZIPOutputStream gzip;
		try {
			gzip = new GZIPOutputStream(out);
			gzip.write(bytes);
			gzip.close();
		} catch (IOException e) {
		}
		return out.toByteArray();
	}

	/**
	 * 字符串的解压
	 *
	 * @param bytes
	 *            对字符串解压
	 * @return 返回解压缩后的字符串
	 * @throws IOException
	 */
	public static byte[] uncompress(byte[] bytes) {
		if (bytes == null || bytes.length == 0) {
			return null;
		}
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		ByteArrayInputStream in = new ByteArrayInputStream(bytes);
		try {
			GZIPInputStream ungzip = new GZIPInputStream(in);
			byte[] buffer = new byte[256];
			int n;
			while ((n = ungzip.read(buffer)) >= 0) {
				out.write(buffer, 0, n);
			}
		} catch (IOException e) {
		}
		return out.toByteArray();
	}

	/*
	 * 
	 * 倒序查看日志
	 * 
	 * 
	 */
	public static void ReadLogFile(String fileUrl, int lineCount) {

		if (lineCount == 0) {
			lineCount = 500;
		}
		String[] mes = new String[lineCount];
		if (fileUrl.length() == 0) {
			fileUrl = "D:\\catalina.out";
		}
		String charset = "utf-8";
		RandomAccessFile rf = null;

		try {
			rf = new RandomAccessFile(fileUrl, "r");
			long fileLength = rf.length();
			long start = rf.getFilePointer();// 返回此文件中的当前偏移量
			long readIndex = start + fileLength - 1;
			String line;
			rf.seek(readIndex);// 设置偏移量为文件末尾
			int c = -1;
			while (readIndex > start) {
				c = rf.read();
				if (c == '\n' || c == '\r') {
					line = rf.readLine();
					if (line != null) {
						lineCount = lineCount - 1;
						if (lineCount == 0) {
							break;
						}
						mes[lineCount] = "" + new String(line.getBytes("ISO-8859-1"), charset);
					}
					readIndex--;
				}
				readIndex--;
				rf.seek(readIndex);
				if (readIndex == 0) {// 当文件指针退至文件开始处，输出第一行
					System.out.println(rf.readLine());
				}
			}
			for (int i = 0; i < mes.length; i++) {
				System.out.println(mes[i]);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (rf != null)
					rf.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	public static void main(String[] args) {
		ReadLogFile("D:\\catalina.out", 500);
	}
}
